//位置数组
let nums = new Array();  
let score = 0;  //当前分数
let hasConflicted = new Array();    //标记单元格是否做过叠加，true表示叠加过，false表示未叠加

//页面加载完成之后就调用Newgame方法去生成数字格子
$(document).ready(function(){
    Newgame();
});


//页面的新游戏按钮被点击时调用此方法，创建新游戏
function Newgame(){
    init();
    //界面中随机产生两个数
    generateOneNumber();
    generateOneNumber();
};

//创建新游戏后初始化界面
function init(){
    //初始化单元格位置
    for (let i = 0; i < 4; i++){
        for (let j = 0; j < 4; j++){
            let gridCell = $("#grid-cell-" + i + "-" + j);//循环遍历来获取每个格子
            gridCell.css('top',getPosTop(i));   //getPosTop方法来获取上边距 然后给对应格子加上top和left属性,配合循环的自增，格子就会变成4X4样式
            gridCell.css('left',getPosLeft(j));  //getPosLeft方法来获取左边距
			//不加此css的话，所有格子都会重叠在一起
        }
    }

    //初始化数组
    for (let i = 0; i < 4; i++){
        nums[i] = new Array();    //生成nums数组nums[1],2,3,4 对应4X4的格子
        hasConflicted[i] = new Array();    //生成标识是否做过叠加
        for(let j = 0; j < 4; j++){
            nums[i][j] = 0;			//然后遍历循环，每个格子都赋值为0
            hasConflicted[i][j] = false;    //所有格子都标识为 为叠加
        }
    }

    //动态创建上层单元格
    updateView();
    //分数归零
    score = 0;
    updateScore(score);  //更新分数
};

//更新上层单元格视图
function updateView(){
    //清空单元格
    $('.number-cell').remove();

    for(let i = 0; i < 4; i++){
        for(let j = 0; j < 4; j++){
            $('#container').append('<div class="number-cell" id="number-cell-'+i+'-'+j+'"></div>') //通过循环来把新的格子加到container中
			//然后通过以下方法，将一个div悬浮到格子的上方，并没有替换原本的格子
            let numberCell = $('#number-cell-'+i+'-'+j);

            if(nums[i][j] == 0){
                numberCell.css('width','0px');
                numberCell.css('height','0px');
                numberCell.css('top',getPosTop(i)+50);
                numberCell.css('left',getPosLeft(j)+50);
            }else {
                numberCell.css('width','100px');
                numberCell.css('height','100px');
                numberCell.css('top',getPosTop(i));
                numberCell.css('left',getPosLeft(j));
                numberCell.css('background-color',getNumberBackgroundColor(nums[i][j]));
                numberCell.css('color',getNumberColor(nums[i][j]));
                numberCell.text(nums[i][j]);
            }
        hasConflicted[i][j] = false;
        }
    }
}





/*
    在剩余的单元格中随机产生一个数：
    1、在空余的单元格中随机找一个
    2、随机产生一个2或4
*/
function generateOneNumber(){
    if(noSpace(nums)){ //调用noSpace方法去判断有没有空的
        return;  //如果没有空间了就停下生成数字
    }

    //在空余单元格中找到一个随机位置
    let count = 0;
    let temp = new Array();
	var a=0;
    for (let i = 0; i < 4; i++){
        for (let j = 0; j < 4; j++){
            if (nums[i][j] == 0){  //等于0就是空格子
               //原代码会因为错误判断格子的位置而导致数字出错，我替换了新的定位方法
				temp[a]=i+","+j;
				a++;	
            }
        }
    }
	//原代码会因为错误判断格子的位置而导致数字出错，我替换了新的定位方法
	var number=Math.floor((Math.random()*temp.length)); //得到行坐标
	var m=temp[number].split(",");//按,分割坐标字符串，m0就是行，m1就是列
    //在随机的位置上产生一个随机数
    let randNum = Math.random() < 0.5 ? 2 : 4;

    //在随机位置上显示随机数字
	
	nums[m[0]][m[1]] = randNum;
	showNumberWithAnimation(m[0],m[1],randNum);

}












//获取距离上边的位置
function getPosTop(i){
    return 20 + 120 * i;
}

//获取距离左边的位置
function getPosLeft(j){
    return 20 + 120 * j;
}



//更新显示分数
function updateScore(score){
    $('#score-number').text(score);
}





//判断没有空间
function noSpace(nums){
    for (let i = 0; i < 4; i++){
        for (let j = 0; j < 4; j++){
            if(nums[i][j] == 0) //循环判断nums数组里面的值是不是等于0，如果等于0的话就返回false
                return false;
        }
    }
    return true; //如果每个格子都不等于0的话，就是没有空间了，返回true
}



//随机生成单元格动画
function showNumberWithAnimation(i,j,n){
    //console.log(i,j,n);
    let numberCell = $('#number-cell-'+i+'-'+j);  //通过传进来的坐标获取对应格子
    numberCell.css('background-color',getNumberBackgroundColor(n));  //然后给格子添加随机的背景色
    numberCell.css('color',getNumberColor(n)); //添加随机字体颜色
    numberCell.text(n); //然后把随机分数添加进去

	//通过一个0.5秒的动画去让数字慢慢出现
    numberCell.animate({
        width:'100px',
        height:'100px',
        top:getPosTop(i),
        left:getPosLeft(j)
    },200)
}

//移动单元格动画
function showMoveAnimation(fx,fy,tox,toy){
    let numberCell = $('#number-cell-'+fx+'-'+fy);
    numberCell.animate({
        top:getPosTop(tox),
        left:getPosLeft(toy)
    },200)
}

//获取数字背景颜色
function getNumberBackgroundColor(num){
    switch(num){
        case 2:return "#eee4da";
        case 4:return "#ede0c8";
        case 8:return "#f2b179";
        case 16:return "#f59563";
        case 32:return "#f67c5f";
        case 64:return "#f65e3b";
        case 128:return "#edcf72";
        case 256:return "#edcc61";
        case 512:return "#9c0";
        case 1024:return "#33b5e5";
        case 2048:return "#09c";
        case 4096:return "#a6c";
        case 8192:return "#93c";
    }
}

//获取数字颜色
function getNumberColor(num){
    if(num<=4){
        return '#776e65';
    }else{
        return '#fff';
    }
}




//这里放键盘响应事件，也就是上下左右
$(document).keydown(function (event){
    //阻止事件的默认动作
    //event.preventDefault();  //调用此方法是为了按上下左右时，页面不会跟着一起移动
    switch (event.keyCode) {
        case 37: //left
            //判断是否可以向左移动
            if(canMoveLeft(nums)){
                moveLeft();
                setTimeout(generateOneNumber,200);
                setTimeout(isGameOver,500);
            }
            break;
        case 38://up
            if(canMoveUp(nums)){
                moveUp();
                setTimeout(generateOneNumber,200);
                setTimeout(isGameOver,500);
            }
            break;
        case 39://right
            if(canMoveRight(nums)){
                moveRight();
                setTimeout(generateOneNumber,200);
                setTimeout(isGameOver,500);
            }
            break;
        case 40://down
            if(canMoveDown(nums)){
                moveDown();
                setTimeout(generateOneNumber,200);
                setTimeout(isGameOver,500);
            }
            break;
        default:break;
    }
})



//判断是否可以向左移动
function canMoveLeft(nums){
    for (let i = 0; i < 4; i++){
        for (let j = 0; j < 4; j++){
            if(nums[i][j] != 0){
                if(nums[i][j-1] == 0 || nums[i][j] == nums[i][j-1] ){ //==0就表示左边的格子是空的，两个相等就表示可以合并
                    return true;
                }
            }
        }
    }
    return false;
}


function canMoveRight(nums){
	for(let i=0;i<4;i++){
		for(let j=0;j<4;j++){
			if(nums[i][j]!=0){
				if(nums[i][j+1] == 0 || nums[i][j] == nums[i][j+1] ){ //==0就表示左边的格子是空的，两个相等就表示可以合并
				    return true;
				}
			}
		}
	}
}

//判断是否可以向上移动
function canMoveUp(nums){
    for(var i=1;i<4;i++){
        for(var j=0;j<4;j++){
            if(nums[i][j]!=0){
                if(nums[i-1][j]==0 || nums[i-1][j]==nums[i][j]){
                    return true;
                }
            }
        }
    }
    return false;
}

//判断是否可以向下移动
function canMoveDown(nums){
    for(var i=0;i<3;i++){
        for(var j=0;j<4;j++){
            if(nums[i][j]!=0){
                if(nums[i+1][j]==0 || nums[i+1][j]==nums[i][j]){
                    return true;
                }
            }
        }
    }
    return false;
}



//判断是否不能移动
function noMove(nums){
    if(canMoveLeft(nums) || canMoveRight(nums) || canMoveUp(nums) || canMoveDown(nums)){
        return false;
    }
    return true;
}

//判断游戏是否结束，两个条件：1.没有空单元格  2.不能移动
function isGameOver(){
    if(noSpace(nums) && noMove(nums)){
        dianwo();
    }
}

/*
    向左移动
    需要对每个数字进行判断选择合适的落脚点，落脚点有两种情况:
        1、落脚点没有数字，并且移动的路径中没有障碍物
        2、落脚点数字和自己相同，并且移动的路径中没有障碍物
*/
function moveLeft(){
    for (let i = 0;i<4;i++){
        for (let j=0;j<4;j++){
			console.log(nums[i][j]);
            if(nums[i][j] != 0 ){ //空格子是不需要移动的，所以这里要加一层判断，格子是不是有值
                for (let k=0;k<j;k++){  //向左移动的时候，只需要改变横坐标，所以k只需要小于j即可
                    if(nums[i][k]===0 && noBlockHorizontal(i,k,j,nums)){     //判断第i行的第k-j之间是否有障碍物
                        //移动单元格
                        showMoveAnimation(i,j,i,k);
                        nums[i][k] = nums[i][j];
                        nums[i][j] = 0;
                        break;
                    }else if(nums[i][k] === nums[i][j] && noBlockHorizontal(i,k,j,nums) && !hasConflicted[i][k]){    //判断落脚点数字是否和自己相同且移动路径无障碍
                        //移动单元格
                        showMoveAnimation(i,j,i,k);//移动动画效果
						console.log("向左移动1111");
                        nums[i][k] += nums[i][j];  //可以叠加，所以两个数相加之后，原来的位置变成0
                        nums[i][j] = 0;
                        //统计分数
                        score += nums[i][k];
                        //更新分数
                        updateScore(score);
                        //更新叠加判断
                        hasConflicted[i][k] = true; //表示已经叠加
                        break;
                    }

                }
            }
        }
    }
    setTimeout(updateView,200);
}

//向右移动
function moveRight(){
    for (let i = 0;i<4;i++){
        for (let j=3;j>=0;j--){
            if(nums[i][j] != 0 ){
                for (let k=3;k>j;k--){
                    if(nums[i][k]===0 && noBlockHorizontal(i,j,k,nums)){     //判断第i行的第k-j之间是否有障碍物
                        //移动单元格
                        showMoveAnimation(i,j,i,k);
                        nums[i][k] = nums[i][j];
                        nums[i][j] = 0;
                        break;
                    }else if(nums[i][k] === nums[i][j] && noBlockHorizontal(i,j,k,nums) && !hasConflicted[i][k]){    //判断落脚点数字是否和自己相同且移动路径无障碍
                        //移动单元格
                        showMoveAnimation(i,j,i,k);
						
						console.log("向右移动1111");
						console.log(nums[i][k]);
						console.log(nums[i][j]);
                        nums[i][k] += nums[i][j];
                        nums[i][j] = 0;
						console.log(nums[i][k]);
						console.log("移动结束");
						console.log("************");
                        //统计分数
                        score += nums[i][k];
                        //更新分数
                        updateScore(score);

                        //更新叠加判断
                        hasConflicted[i][k] = true; //表示已经叠加
                        break;
                    }
					
                }
            }
        }
    }
    setTimeout(updateView,200);
}

//向上移动
function moveUp(){
    for(var j=0;j<4;j++){
        for(var i=0;i<4;i++){
            if(nums[i][j]!=0){
				
                for(var k=0;k<i;k++){
					//还得再加一个判断，如果遇到需要合并两次的情况，就不要再限制hasConflicted

                    if(nums[k][j]===0 && noBlockVertical(j,k,i,nums)){ //第j列的第k-i行之间是否有障碍物
                        showMoveAnimation(i,j,k,j);
                        nums[k][j]=nums[i][j];
                        nums[i][j]=0;
                        break;
                    }else if(nums[k][j]==nums[i][j] && noBlockVertical(j,k,i,nums) && !hasConflicted[k][j]){
                        showMoveAnimation(i,j,k,j);
						
						console.log("向上移动1111");
						console.log(nums[k][j]);
						console.log(nums[i][j]);
                        nums[k][j]+=nums[i][j];
                        nums[i][j]=0;
						console.log(nums[k][j]);
						console.log("移动结束");
						console.log("************");

                        score+=nums[k][j];
                        updateScore(score);

                        hasConflicted[k][j]=true;
                        break;
                    }
					
					
                }
            }
        }
    }
    setTimeout(updateView,200);
}

//向下移动
function moveDown(){
    for(var j=0;j<4;j++){
        for(var i=3;i>=0;i--){
            if(nums[i][j]!=0){
                for(var k=3;k>i;k--){
                    if(nums[k][j]===0 && noBlockVertical(j,i,k,nums)){ //第j列的第i-k行之间是否有障碍物
                        showMoveAnimation(i,j,k,j);
                        nums[k][j]=nums[i][j];
                        nums[i][j]=0;
                        break;
                    }else if(nums[k][j]===nums[i][j]  && noBlockVertical(j,i,k,nums) && !hasConflicted[k][j]){
                        showMoveAnimation(i,j,k,j);
						console.log("向下移动1111");
						console.log(nums[k][j]);
						console.log(nums[i][j]);
                        nums[k][j]+=nums[i][j];
                        nums[i][j]=0;
						console.log(nums[k][j]);
						console.log("移动结束");
						console.log("************");

                        score+=nums[k][j];
                        updateScore(score);

                        hasConflicted[k][j]=true;
                        break;
                    }
					
					
					
                }
            }
        }
    }
    setTimeout(updateView,200);
}

//判断k-j之间没有障碍物
function noBlockHorizontal(row,col1,col2,nums){
    for (let i=col1+1;i<col2;i++){
        if(nums[row][i]!=0){   //如果传过来的行  col1到col2之间都是空格的话，那么就表示中间没有障碍物
            return false
        }
    }
    return true
}

//判断垂直方向上是否没有障碍物
function noBlockVertical(col,row1,row2,nums){
    for(let i=row1+1;i<row2;i++){
        if(nums[i][col]!=0){
            return false;
        }
    }
    return true;
}

function dianwo(){
		document.getElementById('zhezhao').style.display="";
}
function hidder(){
		document.getElementById('zhezhao').style.display="none";
}
function button_new_game(){
		document.getElementById('zhezhao').style.display="none";
		Newgame();
							
}


